import { reactive, ref } from 'vue'
import { ElMessage, dayjs, type FormRules } from 'element-plus'
import { AsyncRecursion, creatAsyncRecursion } from '@src/utils/asyncRecursion'
import { exportJson, promisetTimeOut } from '@src/utils/common'

import type { NodeMsg, RuleForm, SheetExel, OneNodeOriginData } from './type'
import { dealValue, defaultNodeData, getAllNodeData, getMinMaxDifferenc, validateNodes, validateUniqueCode } from "./generate";
import { betweenStartEndDays, startAutoGetdata, stopAutoGetdata, validateTimeMinute } from '../../generate';
import { yunNao } from "@src/api/yunNao";

  /**
   * 【现货市场】-【现货交易】-【日前交易结果】-【一次日前节点电价查询】
   * 全网所有节点日前出清节点电价
   * D + 1
   * AHEAD_NODE_PRICE_INFO = "ahead_node_price_info"
   */
  /**
   * https://pmos.sd.sgcc.com.cn:18080/trade/main/home/changeDate.do?pdate=2024-03-19&_=1711692352927
   * 【现货市场】-【现货交易】-【实时交易结果】-【实时节点电价查询】
   * 全网所有节点实时出清节点电价-临时
   * D - 1
   * ACT_NODE_PRICE_INFO = "act_node_price_info",
   */

export const useNodeData = (ruleFormRef:any) => {

  const loading = ref(false)

  const reqHistory = ref<{ certainDate: string, reqTypes: string }[]>([])

  const sheetExcelData = ref<SheetExel>()

  const ruleForm = reactive<RuleForm>({
    certainDate: [dayjs().format('YYYY-MM-DD'), dayjs().format('YYYY-MM-DD')],
    // reqType: DataSourceTypeEnum.AHEAD_NODE_PRICE_INFO,
    uniqueCode:'',
    node: JSON.stringify(defaultNodeData)
  })

  let pickedStartDate:Date | null = null
  const calendarChange = (pickedDate:Date[]) => {
    const [min, max] = pickedDate
    if (max) {
      pickedStartDate = null
    } else {
      pickedStartDate = min
    }
  }

  /** 最多选择10天的时间 */
  const disabledDate = (date: Date) => {
    const appEnv = import.meta.env.VITE_APP_ENV
    if(/^dev/.test(appEnv)) return false
    
    const theTime = date.getTime()

    if (!pickedStartDate) return false

    const minDate = dayjs(pickedStartDate).subtract(366, 'day').valueOf()
    const maxDate = dayjs(pickedStartDate).add(366, 'day').valueOf()

    return theTime < minDate || theTime > maxDate
  }

  const rules = reactive<FormRules<RuleForm>>({
    certainDate: [
      { required: true, message: '请选择数据日期', trigger: 'blur' },
    ],
    node: [{ validator: validateNodes, trigger: 'change' }],
    uniqueCode: [
      {
        required: true,
        message: '请输入验证码',
        trigger: 'blur',
      },
      { validator: validateUniqueCode, trigger: 'blur' }
    ]
  })

  /** 显示请求成功的历史 */
  const setReqHistory = (certainDate:string) => {
    reqHistory.value.unshift({
      certainDate,
      reqTypes:  '日前和实时'
    })
  }

  const initSheetExcel = () => {
    const {certainDate, node} = ruleForm
    const nodeObj = JSON.parse(node) as NodeMsg
    sheetExcelData.value = {
      data: [
        {
          sheetData: [['时间', '日前', '实时']],
          sheetName: `${nodeObj.nodeName}详细数据`
        },
        {
          sheetData: [['时间', '日前最大', '日前最小', '日前峰谷价差', '', '实时最大', '实时最小', '实时峰谷价差']],
          sheetName: `${nodeObj.nodeName}峰谷价差`
        }
      ],
      dateStart: certainDate[0].replace(/-/g, ''),
      dateEnd: certainDate[1].replace(/-/g, ''),
      fileName: `${nodeObj.nodeName}${dayjs(certainDate[0]).format('YYYYMMDD')}至${dayjs(certainDate[1]).format('YYYYMMDD')}`
    }
  }

  const dealOneDayNode = ({aheadData, actData, certainDate}:{ aheadData: OneNodeOriginData, actData: OneNodeOriginData, certainDate:string}) => {
    const {pointList, Val: aheadVal = []} = aheadData
    const {Val: actVal = []} = actData
    if(!sheetExcelData.value?.data) return
    pointList.forEach((timePoint, index) => {
      if(!sheetExcelData.value?.data) return
      const time = `${certainDate.replace(/-/g, '/')} ${timePoint}`
      const aheadValue = dealValue(aheadVal?.[index])
      const actValue = dealValue(actVal?.[index])
      sheetExcelData.value.data[0].sheetData.push([time, aheadValue, actValue])
    })
    
    sheetExcelData.value.data[1].sheetData.push([certainDate, ...getMinMaxDifferenc(aheadVal), '', ...getMinMaxDifferenc(actVal)])
  }

  /** 请求一天的数据 */
  const reqOneCertainDateData = async (certainDate:string) => {
    try {
      const nodeData = await getAllNodeData({...ruleForm, certainDate}, undefined, JSON.parse(ruleForm.node))
      dealOneDayNode(nodeData)
      setReqHistory(certainDate)
    }catch(e) {
      console.error(e)
      ElMessage.error('获取数据失败！ 请刷新主系统和子系统后重试')
    }
  }

  const downLoadExcelOrJson = async () => {
    const appEnv = import.meta.env.VITE_APP_ENV
    if(!sheetExcelData.value || Number(sheetExcelData.value?.data?.[0]?.sheetData?.length) < 2) {
      ElMessage.error('获取数据失败')
      return Promise.reject(new Error('获取数据失败'))
    }

    if(appEnv === 'development') {
      await yunNao.sheetExcel(sheetExcelData.value)
      ElMessage.success('数据获取成功，Excel文件即将下载完成')
      return
    }

    exportJson(sheetExcelData.value.fileName, JSON.stringify(sheetExcelData.value))
    ElMessage.success('数据获取成功，JSON文件即将下载完成')
  }

  const reqData = async () => {
    stopAutoGetdata()
    try {
      loading.value = true
      initSheetExcel()
    
      await creatAsyncRecursion(AsyncRecursion, {
        stepAsyncFnParamsList: betweenStartEndDays(ruleForm.certainDate[0], ruleForm.certainDate[1]),
        stepAsyncFn: reqOneCertainDateData,
        stepCb: async () => await promisetTimeOut(1000), // 每天延时 1s
        stepAsyncNum: 1,
        errBreak: true
      }).start()

      downLoadExcelOrJson()
    }catch(e) {
      console.error(e)
      ElMessage.error('获取数据失败！ 请刷新主系统和子系统后重试')
    }finally {
      loading.value = false
      startAutoGetdata()
    }
  }

  const submitForm = async () => {
    if (!ruleFormRef?.value) return
    if(!validateTimeMinute()) return
    await ruleFormRef.value.validate()
    reqData()
  }

  const resetForm = () => {
    if (!ruleFormRef?.value) return
    ruleFormRef.value.resetFields()
  }

  return {
    loading,
    ruleForm,
    rules,
    submitForm,
    resetForm,
    reqHistory,
    disabledDate,
    calendarChange
  }
}
